<?php
namespace app\common\util;

use think\Config;
use think\Exception;
use think\Log;
use think\Request;

class ImageUpload
{
    /**
     * 上传多个图片文件
     * @param array $imageObjects 前端传来的图片对象数组
     * @param string $savePath 保存路径
     * @param array $allowedTypes 允许的文件类型
     * @param int $maxSize 最大文件大小(字节)
     * @param bool $generateThumbnail 是否生成缩略图
     * @param array $thumbnailOptions 缩略图配置
     * @return array 返回上传结果
     */
    public static function uploadMultiple($imageObjects, $savePath = 'uploads/images/', $allowedTypes = ['jpg', 'jpeg', 'png', 'gif'], $maxSize = 10485760, $generateThumbnail = false, $thumbnailOptions = ['width' => 200, 'height' => 200])
    {
        // 确保保存路径存在
        self::createDirectory($savePath);
        
        $result = [
            'success' => [],
            'error' => []
        ];
        
        foreach ($imageObjects as $key => $imageObject) {
            $uploadResult = self::uploadSingle($imageObject, $savePath, $allowedTypes, $maxSize, $generateThumbnail, $thumbnailOptions);
            
            if ($uploadResult['status']) {
                $result['success'][] = $uploadResult;
            } else {
                $result['error'][] = [
                    'index' => $key,
                    'name' => $imageObject->name,
                    'message' => $uploadResult['message']
                ];
            }
        }
        
        return $result;
    }
    
    /**
     * 上传单个图片文件
     * @param object $imageObject 前端传来的图片对象
     * @param string $savePath 保存路径
     * @param array $allowedTypes 允许的文件类型
     * @param int $maxSize 最大文件大小(字节)
     * @param bool $generateThumbnail 是否生成缩略图
     * @param array $thumbnailOptions 缩略图配置
     * @return array 返回上传结果
     */
    private static function uploadSingle($imageObject, $savePath, $allowedTypes, $maxSize, $generateThumbnail, $thumbnailOptions)
    {
        $result = [
            'status' => false,
            'message' => '',
            'data' => []
        ];
        
        try {
            // 获取文件名和扩展名
            $fileName = $imageObject->name;
            // halt($fileName);
            $fileInfo = pathinfo($fileName);
            // halt($fileInfo);
            $extension = strtolower($fileInfo['extension']);
            
            // 检查文件类型
            if (!in_array($extension, $allowedTypes)) {
                $result['message'] = '不允许的文件类型: ' . $extension;
                return $result;
            }
            
            // 检查文件大小
            if ($imageObject->size > $maxSize) {
                $result['message'] = '文件大小超过限制: ' . round($imageObject->size/1024/1024, 2) . 'MB';
                return $result;
            }
            
            // 处理Base64数据 - 移除数据类型前缀
            $base64Data = $imageObject->base64Content;
            $base64Data = preg_replace('/^data:image\/[a-z]+;base64,/', '', $base64Data);
            
            $fileData = base64_decode($base64Data);
            
            if ($fileData === false) {
                $result['message'] = 'Base64解码失败';
                return $result;
            }
            
            // 验证解码后的文件大小
            $decodedSize = strlen($fileData);
            if ($decodedSize > $maxSize) {
                $result['message'] = '解码后的文件大小超过限制: ' . round($decodedSize/1024/1024, 2) . 'MB';
                return $result;
            }
            
            // 生成新文件名
            $newFileName = date('YmdHis') . '_' . $fileName;
            $saveFilePath = $savePath . $newFileName;

            // halt($saveFilePath);
            
            // 保存文件
            $filePath = ROOT_PATH . 'public' . DS . $saveFilePath;
            $fileUrl = Request::instance()->domain() . '/' . $saveFilePath;
            // halt($fileUrl);
            
            // 检查文件是否已存在
            if (file_exists($filePath)) {
                $newFileName = date('YmdHis') . '_' . '_' . rand(1000, 9999) . $fileName;
                $saveFilePath = $savePath . $newFileName;
                $filePath = ROOT_PATH . 'public' . DS . $saveFilePath;
                $fileUrl = Request::instance()->domain() . '/' . $saveFilePath;
            }
            
            if (file_put_contents($filePath, $fileData) === false) {
                $result['message'] = '文件保存失败';
                return $result;
            }
            
            // 验证图片有效性
            if (!self::validateImage($filePath)) {
                // 删除无效图片
                @unlink($filePath);
                $result['message'] = '无效的图片文件';
                return $result;
            }
            
            // 生成缩略图
            $thumbnailPath = '';
            $thumbnailUrl = '';
            
            if ($generateThumbnail) {
                $thumbnailFileName = 'thumb_' . $newFileName;
                $thumbnailFilePath = $savePath . $thumbnailFileName;
                $fullThumbnailPath = ROOT_PATH . 'public' . DS . $thumbnailFilePath;
                $thumbnailUrl = Request::instance()->domain() . '/' . $thumbnailFilePath;
                
                try {
                    // 使用原生PHP函数生成缩略图
                    if (self::createThumbnail($filePath, $fullThumbnailPath, $thumbnailOptions['width'], $thumbnailOptions['height'])) {
                        $thumbnailPath = $thumbnailFilePath;
                    }
                } catch (Exception $e) {
                    Log::error('生成缩略图失败: ' . $e->getMessage());
                    // 缩略图生成失败不影响主图片上传
                }
            }
            
            // 返回成功结果
            $result['status'] = true;
            $result['message'] = '上传成功';
            $result['data'] = [
                'original_name' => $fileName,
                'file_name' => $newFileName,
                'file_path' => $saveFilePath,
                'file_url' => $fileUrl,
                'thumbnail_path' => $thumbnailPath,
                'thumbnail_url' => $thumbnailUrl,
                'size' => $imageObject->size,
                'type' => $imageObject->type
            ];
            
        } catch (Exception $e) {
            $result['message'] = '上传过程中发生错误: ' . $e->getMessage();
            Log::error('图片上传错误: ' . $e->getMessage());
        }
        
        return $result;
    }
    
    /**
     * 创建目录
     * @param string $path 目录路径
     * @return bool
     */
    private static function createDirectory($path)
    {
        $dir = ROOT_PATH . 'public' . DS . $path;
        if (!is_dir($dir)) {
            return mkdir($dir, 0755, true);
        }
        return true;
    }
    
    /**
     * 验证图片有效性
     * @param string $filePath 文件路径
     * @return bool
     */
    private static function validateImage($filePath)
    {
        try {
            $imageInfo = @getimagesize($filePath);
            if ($imageInfo === false) {
                return false;
            }
            
            // 验证MIME类型
            $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
            return in_array($imageInfo['mime'], $allowedMimeTypes);
        } catch (Exception $e) {
            return false;
        }
    }
    
    /**
     * 使用PHP原生函数创建缩略图
     * @param string $sourcePath 源图片路径
     * @param string $targetPath 目标缩略图路径
     * @param int $maxWidth 最大宽度
     * @param int $maxHeight 最大高度
     * @return bool
     */
    private static function createThumbnail($sourcePath, $targetPath, $maxWidth, $maxHeight)
    {
        // 获取图片信息
        $imageInfo = getimagesize($sourcePath);
        $width = $imageInfo[0];
        $height = $imageInfo[1];
        $mime = $imageInfo['mime'];
        
        // 计算缩略图尺寸
        $ratio = min($maxWidth / $width, $maxHeight / $height);
        $newWidth = intval($width * $ratio);
        $newHeight = intval($height * $ratio);
        
        // 创建缩略图画布
        $thumbnail = imagecreatetruecolor($newWidth, $newHeight);
        
        // 根据图片类型创建源图像
        switch ($mime) {
            case 'image/jpeg':
                $source = imagecreatefromjpeg($sourcePath);
                break;
            case 'image/png':
                $source = imagecreatefrompng($sourcePath);
                // 保留PNG透明度
                imagealphablending($thumbnail, false);
                imagesavealpha($thumbnail, true);
                break;
            case 'image/gif':
                $source = imagecreatefromgif($sourcePath);
                break;
            default:
                return false;
        }
        
        // 调整大小
        imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
        
        // 保存缩略图
        $success = false;
        switch ($mime) {
            case 'image/jpeg':
                $success = imagejpeg($thumbnail, $targetPath, 80);
                break;
            case 'image/png':
                $success = imagepng($thumbnail, $targetPath);
                break;
            case 'image/gif':
                $success = imagegif($thumbnail, $targetPath);
                break;
        }
        
        // 释放内存
        imagedestroy($source);
        imagedestroy($thumbnail);
        
        return $success;
    }
    
    /**
     * 删除图片文件
     * @param string $filePath 文件路径
     * @param string $thumbnailPath 缩略图路径(可选)
     * @return bool
     */
    public static function deleteImage($filePath, $thumbnailPath = '')
    {
        $success = true;
        
        // 删除原图
        $fullFilePath = ROOT_PATH . 'public' . DS . $filePath;
        if (file_exists($fullFilePath) && !@unlink($fullFilePath)) {
            $success = false;
            Log::error('删除图片失败: ' . $fullFilePath);
        }
        
        // 删除缩略图
        if (!empty($thumbnailPath)) {
            $fullThumbnailPath = ROOT_PATH . 'public' . DS . $thumbnailPath;
            if (file_exists($fullThumbnailPath) && !@unlink($fullThumbnailPath)) {
                $success = false;
                Log::error('删除缩略图失败: ' . $fullThumbnailPath);
            }
        }
        
        return $success;
    }
}
?>
